const { Service } = require('egg')
const cheerio = require('cheerio')
const { tableToList, getTerm } = require('../utils/tools')

/**
 * 根据输入的成绩字符串判断其状态。
 * @param {string} str 表示成绩的字符串，可以是数字或者文字。
 * @return {Array} 返回一个包含两个元素的数组。第一个元素是输入的成绩字符串，第二个元素是成绩的状态，
 *                  如果成绩是数字，则状态为'已获'（及格）或'已开未获'（不及格）；如果成绩是文字，则状态为'已获'（及格）或'已开未获'（不及格）。
 */
const gradeStatus = (str) => {
  if (/^\d+$/.test(str)) { // 如果输入的是数字
    return [str, (Number(str) >= 60) ? '已获' : '已开未获'] // 判断数字是否及格，及格则返回'已获'，否则返回'已开未获'
  }
  return [str, str === '不及格' ? '已开未获' : '已获'] // 如果输入的是文字，判断是否为'不及格'，是则返回'已开未获'，否则返回'已获'
}

module.exports = class CreditService extends Service {
  /**
   * 学分修读情况
   * @return {Array} *
   */
  async table() {
    // 身份识别信息+学号(获取入学年份),sid-学号
    const Cookie = this.ctx.state.Cookie
    const sid = this.ctx.data.sid
    // 对学号进行处理，得到入学年份
    const year = sid.slice(0, 4)
    // 结果保存容器
    const result = []
    // 访问最初的学生完成情况(体系)页面，获取个人识别关键信息ndzydm属性值,ccs-学生完成情况，fir-first
    const ccsFir = `${this.ctx.state.baseUrl}/jsxsd/xxwcqk/xxwcqk_idxOntx.do`

    // 发送请求，获取网页内容
    const resCcs1 = await this.ctx.curl(ccsFir, {
      method: 'GET',
      headers: {
        Cookie,
        // 'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      timeout: 10000,
    })
    // 请求状态200检查
    if (resCcs1.status === 200) {
      try {
        // 加载网页内容
        const $ = cheerio.load(resCcs1.data.toString())
        // 从网页内容中寻找到ndzydm属性，获取到其中的value值
        const ndzydm = $('*[name="ndzydm"]').val()

        // 正式访问学生完成情况(体系)页面，获取到汇总表,ccs-学生完成情况，sec-second
        const resCcs2 = this.ctx.curl(`${this.ctx.state.baseUrl}/jsxsd/xxwcqk/xxwcqkOnkclb.do`, {
          method: 'POST',
          headers: {
            Cookie,
            // 'Content-Type': 'application/x-www-form-urlencoded',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
          },
          data: {
            ndzydm, // 关键的身份验证码
            jx0301zxjhid: '',
          },
        })

        // 访问培养计划，获取到未修读课程的年份信息，tp-培养计划
        const tpRes = this.ctx.curl(`${this.ctx.state.baseUrl}/jsxsd/pyfa/topyfamx`, {
          method: 'GET',
          headers: {
            Cookie,
            'Content-Type': 'application/x-www-form-urlencoded',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
          },
        })

        // 访问成绩，获取到已修读课程的年份信息
        const sgUrl = `${this.ctx.state.baseUrl}/jsxsd/kscj/cjcx_list`
        const sgRes = this.ctx.curl(sgUrl, {
          method: 'POST',
          data: {
            kksj: '',
            kcxz: '',
            kcmc: '',
            xsfs: 'all',
          },
          headers: {
            Cookie,
            'Content-Type': 'application/x-www-form-urlencoded',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
          },
          timeout: 10000,
        })

        /* 将异步操作完成结果赋值：R1-P1;R2-P2 */
        const [ccs, tp, sg] = await Promise.all([resCcs2, tpRes, sgRes])
        if (ccs.status === 200 && tp.status === 200) {
          // 获取培养计划表格
          const tableTp = tableToList(tp.data.toString(), '#mxh')
          // console.log('tableTp', tableTp)

          // 获取成绩表
          const tableSg = tableToList(sg.data.toString(), '#dataList')
          // console.log('tableSg', tableSg)

          const dictCourse = {}
          const dictNeed = {}
          tableTp.forEach((e, i) => {
            if (i > 0) {
              if (Object.keys(dictNeed).includes(e[5])) dictNeed[e[5]] += Number(e[7])
              else dictNeed[e[5]] = Number(e[7]) || 0
              dictCourse[e[3]] = getTerm(year, e[13])
            }
          })
          tableSg.forEach((e, i) => {
            if (i > 0) dictCourse[e[3]] = e[1]
          })
          // console.log('dictCourse', dictCourse)

          // 获取学生每个分类下的修读分数
          const tableCcs1 = tableToList(ccs.data.toString(), '.Nsb_r_list:first')
          const dict = {}
          tableCcs1.forEach((e) => { dict[e[0]] = e[1] })

          // 获取学生每个分类下的汇总信息表格
          const tableCcs2 = tableToList(ccs.data.toString(), '.Nsb_r_list:last')

          // 遍历汇总信息表格，整合数据内容
          const detial = { }// 键与表格向对应
          let detialTable = []
          let type = ''
          tableCcs2.forEach((e, i) => {
            if (i > 0) {
              if (e[0] === '') {
                detial[type] = {
                  details: detialTable,
                  has: +dict[type],
                  need: type.includes('选修') || type.includes('任选') ? 0 : dictNeed[type],
                }
                type = ''
                detialTable = []
              } else if (type === '') {
                type = e[0]
              } else {
                // 确定内容，删除修读中的信息内容
                if (e[5] !== '修读中') {
                  detialTable.push({
                    N: e[1],
                    T: dictCourse[e[1]] || '',
                    C: e[2],
                    G: e[5],
                    S: gradeStatus(e[5])[1],
                  })
                }
                if (e[5] === '修读中') {
                  detialTable.push({
                    N: e[1],
                    T: dictCourse[e[1]] || '',
                    C: e[2],
                    G: '修读中',
                    S: '',
                  })
                }
              }
            }
          })

          // 去空
          for (const key in detial) {
            if (detial[key].details.length === 0) delete detial[key]
          }
          // console.log('detial', detial)
          // console.log('detial', detial['专业必修课'])

          // 整合
          for (const key in detial) {
            result.push({
              category: key,
              details: detial[key].details.sort((a, b) => {
                if (!a || !b) return 10000
                const semesterPartsA = a.T.split('-') // 分割字符串得到年份和学期
                const semesterPartsB = b.T.split('-')
                if (!semesterPartsA[0] || !semesterPartsB[0]) return 10000

                // 先比较年份
                if (semesterPartsA[0] !== semesterPartsB[0]) {
                  return semesterPartsA[0] - semesterPartsB[0] // 年份不同的情况下，按年份数字排序
                }

                // 年份相同，则比较学期编号，考虑可能的“上”、“下”学期标记
                const semesterIndexA = parseInt(semesterPartsA[2].replace('上', '1').replace('下', '2'), 10)
                const semesterIndexB = parseInt(semesterPartsB[2].replace('上', '1').replace('下', '2'), 10)

                return semesterIndexA - semesterIndexB // 按学期编号排序
              }),
              need: detial[key].need,
              has: detial[key].has,
            })
          }

          // console.log('result', result)
          return result
        }
        return result
      } catch (err) {
        console.log(err)
        throw err
      }
    }
    return result
  }

  /**
   * * 创新学分、素拓分、第二课堂分
   * @return {Array} *
   */
  async extra() {
    const Cookie = this.ctx.state.Cookie
    const apiUrl = `${this.ctx.state.baseUrl}/jsxsd/pyfa/cxxf_query`
    const res = await this.ctx.curl(apiUrl, {
      method: 'GET',
      headers: {
        Cookie,
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      timeout: 10000,
    })

    const header = ['学期', '项目名称', '学分', '编号', '类型', '备注'] // 列名称
    if (res.status === 200) {
      try {
        const tableList = tableToList(res.data.toString(), '#dataList')
        /* [ '序号', '学年学期', '项目编号', '项目名称', '学号', '姓名', '学分', '学分类型', '备注' ]; */

        const columnNeed = [1, 3, 6, 2, 7, 8] // 需要提取的列序号
        if (tableList.length === 0 || tableList[1][0] === '未查询到数据') return { table: [], header, has: '0' }

        const table = []
        let has = 0
        for (let i = 1; i < tableList.length; i++) {
          const tem = []
          columnNeed.forEach((idx) => { tem.push(tableList[i][idx]) })
          if (tem[0]) { table.push(tem) }
          has += Number(tem[2])
        }
        return { table, header, has: `${has}` }
      } catch (err) {
        console.log('err', err)
        throw err
      }
    }
    return { table: [], header, has: '0' }
  }
}
